# 处理notebook环境asyncio冲突问题
import nest_asyncio
nest_asyncio.apply()

import os
from typing import List, Dict, Any
from langchain.agents import AgentExecutor, create_openai_functions_agent
from langchain_openai import ChatOpenAI
from langchain.tools import Tool
from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.memory import ConversationBufferMemory
from langchain.schema import SystemMessage


# 定义创建智能体函数
def create_agent(tools_info: List[Dict], tools_mapping: Dict, print_process: bool = True):
    """
    创建并初始化一个智能代理实例
    
    参数:
        tools_info (List[Dict]): 工具信息列表，每个工具包含名称和描述信息
            格式示例: [{"name": "tool_name", "desc": "tool_description"}, ...]
        tools_mapping (Dict): 工具名称到实际函数实现的映射字典
            格式示例: {"tool_name": tool_function, ...}
        print_process (bool, optional): 是否打印执行过程，默认为True
    
    返回:
        AgentExecutor: 配置好的代理执行器实例，可以用于处理用户输入和执行工具调用
    """
    # 创建工具列表
    tools = []
    for tool_info in tools_info:
        tools.append(
            Tool(
                name=tool_info["name"],
                description=tool_info["desc"],
                func=tools_mapping[tool_info["name"]]
            )
        )
    
    # 创建系统提示
    system_message = SystemMessage(content="""你是一个智能助手，可以帮助用户完成各种任务。
    你可以使用提供的工具来帮助用户。在每次行动之前，请仔细思考下一步应该做什么。
    如果某个行动反复失败，请直接向用户说明问题所在。
    """)
    
    # 创建提示模板
    prompt = ChatPromptTemplate.from_messages([
        system_message,  # 系统角色定义
        MessagesPlaceholder(variable_name="chat_history"),  # 对话历史
        ("human", "{input}"),  # 用户输入
        MessagesPlaceholder(variable_name="agent_scratchpad"),  # 代理思考过程
    ])
    
    # 初始化语言模型
    llm = ChatOpenAI(
        temperature=0,
        model="gpt-4o-mini",
        api_key=os.getenv("OPENAI_API_KEY")
    )
    
    # 创建对话记忆，用于存储历史对话
    memory = ConversationBufferMemory(
        memory_key="chat_history",  # 记忆的键名
        return_messages=True  # 返回消息格式
    )
    
    # 创建agent实例
    agent = create_openai_functions_agent(llm, tools, prompt)
    
    # 创建agent执行器
    agent_executor = AgentExecutor(
        agent=agent,  # 代理实例
        tools=tools,  # 可用工具列表
        memory=memory,  # 对话记忆
        verbose=print_process,  # 是否显示执行过程
        handle_parsing_errors=True  # 处理解析错误
    )
    
    return agent_executor


def process_user_input(user_input: str, tools_info: List[Dict], tools_mapping: Dict, print_process: bool = True):
    """
    处理用户输入并执行相应的工具操作。
     Args:
        user_input (str): 用户的输入文本
        tools_info (List[Dict]): 可用工具的信息列表，每个工具包含其描述和参数信息
        tools_mapping (Dict): 工具名称到实际工具函数的映射字典
        print_process (bool, optional): 是否打印处理过程。默认为True
    Returns:
        工具执行的结果
    """
    # 创建agent执行器
    agent_executor = create_agent(tools_info, tools_mapping, print_process)
    
    # 执行用户输入
    result = agent_executor.invoke({"input": user_input})
    
    return {
        "reply": result["output"],
        "process_results": result.get("intermediate_steps", [])
    }

if __name__ == "__main__":
    # 测试代码
    from local_utils import tools_info, tools_mapping
    test_input = "北京有什么好玩的地方？"
    result = process_user_input(test_input, tools_info, tools_mapping)
    print("最终回复:", result["reply"])
    print("执行过程:", result["process_results"])